#include "ThreadPool.h"


ThreadPool::ThreadPool(int threadNum)
:_isStop(false)
{
    //初始化_threads中的线程
    for(int i = 0; i < threadNum; i++)
    {
        _threads.emplace_back(std::thread(&ThreadPool::doTask,this));
    }
}
ThreadPool::~ThreadPool()
{
    stop();
}

//增加任务的函数中要加锁
void ThreadPool::addTask(std::shared_ptr<MyTask> task)
{
    {
        std::unique_lock<std::mutex> locker(_mutex);
        bool empty = _taskQueue.isEmpty();
        
        if(_isStop){
            std::cout<<"线程池已经关闭，无法添加任务"<<std::endl;
            return;
        }
        _taskQueue.addTask(task);
    }

    _cond.notify_one();//唤醒一个线程去处理任务

    
}

//读取任务函数不要在内部加锁，因为一般调用getTask的时候已经在外部加锁了
std::shared_ptr<MyTask> ThreadPool::getTask()
{
    return _taskQueue.getTask();
}
void ThreadPool::start()
{
    _isStop=false;
}
void ThreadPool::stop()
{

    _isStop=true;
    //处理完成队列中的任务
    _cond.notify_all();//唤醒所有线程去处理任务


    //回收线程资源
    int num = 0;
    for(auto& thread : _threads)
    {
        thread.join();

    }

}

void ThreadPool::doTask()
{
    
    while(true)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _cond.wait(lock,[this](){
            return _isStop || !_taskQueue.isEmpty();
        });
        //如果线程池已经关闭，则将队列中的任务处理完毕后退出
        if(_isStop){
            std::cout<<"线程池已经关闭，处理队列中剩余的任务，"<<std::endl;
            while(!_taskQueue.isEmpty())
            {
                auto task = getTask();
                lock.unlock();
                
                auto tid = std::this_thread::get_id();
                
                task->process(tid);
                lock.lock();
            }
            break;
        }
        
        //如果线程池没有关闭，那么就从队列中取出任务进行处理
        auto task = getTask();
        lock.unlock();

        auto tid = std::this_thread::get_id();
        task->process(tid);

    }

}